package com.insurance.modules.claim.service.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.insurance.common.common.ResponseData;
import com.insurance.common.utils.AmountUtils;
import com.insurance.common.utils.PageUtils;
import com.insurance.common.utils.Query;
import com.insurance.modules.claim.dao.ClaimCaseDao;
import com.insurance.modules.claim.entity.*;
import com.insurance.modules.claim.service.*;
import com.insurance.modules.claim.vo.request.CaseCloseRatioReq;
import com.insurance.modules.claim.vo.request.CaseListReq;
import com.insurance.modules.claim.vo.request.CasePayOutRatioReq;
import com.insurance.modules.claim.vo.request.PolicyInfoReq;
import com.insurance.modules.claim.vo.response.*;
import com.insurance.modules.sys.entity.SysUserEntity;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service("claimCaseService")
public class ClaimCaseServiceImpl extends ServiceImpl<ClaimCaseDao, ClaimCaseEntity> implements ClaimCaseService {

    @Autowired
    private PolicyInfoService policyInfoService;
    @Autowired
    private InsuredInfoService insuredInfoService;
    @Autowired
    private ClaimSettlementService claimSettlementService;
    @Autowired
    private SettlementAmountService settlementAmountService;
    @Autowired
    private TreatmentInfoService treatmentInfoService;
    @Autowired
    private ClaimCaseServiceImpl claimCaseService;
    @Autowired
    private CaseImporTaskService caseImporTaskService;

    private int success;
    private int error;

    public void setSuccess(int success) {
        this.success = success;
    }

    public void setError(int error) {
        this.error = error;
    }

    public void setErrorNums(String errorNums) {
        this.errorNums = errorNums;
    }

    /**导入失败的序号*/
    private String errorNums = "";

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<ClaimCaseEntity> page = this.page(
                new Query<ClaimCaseEntity>().getPage(params),
                new QueryWrapper<>()
        );

        return new PageUtils(page);
    }

    @Override
    public Page<CaseListRsp> pageList(Page<CaseListRsp> page, CaseListReq req) {
        List<CaseListRsp> list = getBaseMapper().getCasePageList(page, req);
        return page.setRecords(list);
    }

    @Override
    public List<CaseListExportRsp> pageExportList(CaseListReq req) {
        return getBaseMapper().getCasePageExportList(req);
    }

    @Override
    public String getMaxCaseNo() {
        Long no = getBaseMapper().getMaxCaseNo();
        String caseNo = String.format("%05d", no);
        String str = "GZ";
        //补位数
        Calendar date = Calendar.getInstance();
        int year = date.get(Calendar.YEAR);
        str +=  year + caseNo;
        return str;
    }

    @Override
    public Long getNextCaseNo() {
        return getBaseMapper().getMaxCaseNo();
    }

    public String formatCaseNo(Long no) {
        String caseNo = String.format("%05d", no);
        String str = "GZ";
        //补位数
        Calendar date = Calendar.getInstance();
        int year = date.get(Calendar.YEAR);
        str +=  year + caseNo;
        return str;
    }

    @Override
    public void batchImportExcel(List<CaseListExcelImport> cachedDataList, String taskCode) {
        //重置下属性
        claimCaseService.setSuccess(0);
        claimCaseService.setError(0);
        claimCaseService.setErrorNums("");

        if(CollectionUtils.isNotEmpty(cachedDataList)){
            //取下一个的订单号
            Long nextCaseNo = getNextCaseNo();
            //拆解保存到数据库
            for (CaseListExcelImport temp : cachedDataList) {
                //验证保单号是否存在
//            if(StringUtils.isBlank(temp.getPolicyNo())){
//                continue;
//            }
                //查询保单是否存在
                //去掉保单唯一性校验 ———— 20221124
            /*PolicyInfoEntity policyInfoEntity = policyInfoService.queryByPolicyNo(temp.getPolicyNo());
            if(null != policyInfoEntity){
                continue;
            }*/
                SysUserEntity curUser = (SysUserEntity) SecurityUtils.getSubject().getPrincipal();
                Long userid = curUser.getUserId();
                String username = curUser.getUsername();

                //导入的序号
                log.debug("开始导入序号:" + temp.getNum());
                ResponseData responseData = claimCaseService.doSave(nextCaseNo, temp, curUser, userid, username);
                if(responseData.getCode() == ResponseData.success().getCode()){
                    success++;
                    nextCaseNo++;
                    log.debug("导入成功序号:" + temp.getNum());
                }else{
                    //失败了
                    error++;
                    if(StringUtils.isBlank(errorNums)){
                        errorNums += responseData.getData();
                    }else{
                        errorNums += ","+responseData.getData();
                    }
                    log.debug("导入失败序号:" + temp.getNum());
                }
            }
        }

        CaseImporTaskEntity task = caseImporTaskService.queryByCode(taskCode);
        if(null != task){
            task.setStatus(1);
            task.setMsg(getImportMsg());
            task.setUpdateTime(new Date());
            caseImporTaskService.saveOrUpdate(task);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public ResponseData doSave(Long nextCaseNo, CaseListExcelImport temp, SysUserEntity curUser, Long userid, String username) {
        try {
            // 1.保存出险人信息
            InsuredInfoEntity insuredInfo = new InsuredInfoEntity();
            insuredInfo.setCorpName(temp.getCorpName());
            insuredInfo.setInsuredName(temp.getIInsuredName());
            insuredInfo.setPhone(temp.getPhone());
            insuredInfo.setCertificateNo(temp.getCertificateNo());
            insuredInfoService.save(insuredInfo);
            // 2.保存保单快照
            PolicyInfoReq policyInfo = new PolicyInfoReq();
            policyInfo.setInsuredName(temp.getInsuredName());
            policyInfo.setRegion(temp.getRegion());
            policyInfo.setUnderwriteCorp(temp.getUnderwriteCorp());
            policyInfo.setPolicyNo(temp.getPolicyNo());
            if(StringUtils.isNotBlank(temp.getStartTime())){
                String[] arr = temp.getStartTime().split("~");
                if(arr.length == 2){
                    policyInfo.setStartTime(DateUtil.parseDate(arr[0]));
                    policyInfo.setEndTime(DateUtil.parseDate(arr[1]));
                }
            }
            if(StringUtils.isNotBlank(temp.getPersonnelSort())){
                if(temp.getPersonnelSort().equals("有社保")){
                    policyInfo.setPersonnelSort(1);
                }else if(temp.getPersonnelSort().equals("无社保")){
                    policyInfo.setPersonnelSort(0);
                }
            }
            if(StringUtils.isNotBlank(temp.getOutsourcingFlag())){
                if(temp.getOutsourcingFlag().equals("是")){
                    policyInfo.setOutsourcingFlag(1);
                }else if(temp.getOutsourcingFlag().equals("否")){
                    policyInfo.setOutsourcingFlag(0);
                }
            }
            policyInfo.setInsuredAmount(AmountUtils.wanToFenLong(temp.getInsuredAmount()));
            policyInfoService.save(policyInfo);
            // 3.保存案件信息
            ClaimCaseEntity claimCase = new ClaimCaseEntity();
            String maxCaseNo = formatCaseNo(nextCaseNo);
            claimCase.setCaseNo(maxCaseNo);

            claimCase.setDeptId(curUser.getDeptId());
            claimCase.setInsuredId(insuredInfo.getId());
            claimCase.setInsuredName(temp.getIInsuredName());
            claimCase.setAccidentTime(convertStringToDate(temp.getAccidentTime()));
            claimCase.setPolicyId(policyInfo.getId());
            claimCase.setPolicyNo(policyInfo.getPolicyNo());
            claimCase.setAccidentDescription(temp.getAccidentDescription());
            claimCase.setReporterName(temp.getReporterName());
            claimCase.setReporterPhone(temp.getReporterPhone());
            if(StringUtils.isNotBlank(temp.getAccidentType())){
                if(temp.getAccidentType().equals("医疗")){
                    claimCase.setAccidentType(1);
                }else if(temp.getAccidentType().equals("伤残")){
                    claimCase.setAccidentType(2);
                }else if(temp.getAccidentType().equals("交通死亡")){
                    claimCase.setAccidentType(3);
                }else if(temp.getAccidentType().equals("意外死亡")){
                    claimCase.setAccidentType(4);
                }else if(temp.getAccidentType().equals("突发疾病死亡")){
                    claimCase.setAccidentType(5);
                }
            }
            if(StringUtils.isNotBlank(temp.getAccidentNature())){
                if(temp.getAccidentNature().equals("工作中意外")){
                    claimCase.setAccidentNature(1);
                }else if(temp.getAccidentNature().equals("上下班途中意外")){
                    claimCase.setAccidentNature(2);
                }else if(temp.getAccidentNature().equals("工作中交通事故")){
                    claimCase.setAccidentNature(3);
                }else if(temp.getAccidentNature().equals("上下班途中交通事故")){
                    claimCase.setAccidentNature(4);
                }
            }
            if(StringUtils.isNotBlank(temp.getAccidentLiability())){
                if(temp.getAccidentLiability().equals("主要责任")){
                    claimCase.setAccidentLiability(1);
                }else if(temp.getAccidentLiability().equals("次要责任")){
                    claimCase.setAccidentLiability(2);
                }else if(temp.getAccidentLiability().equals("同等责任")){
                    claimCase.setAccidentLiability(3);
                }else if(temp.getAccidentLiability().equals("全责")){
                    claimCase.setAccidentLiability(4);
                }else if(temp.getAccidentLiability().equals("无责")){
                    claimCase.setAccidentLiability(5);
                }
            }
            claimCase.setSendTime(convertStringToDate(temp.getSendTime()));
            claimCase.setFirstAcceptorId(userid);
            claimCase.setFirstAcceptorName(username);
            Date date = new Date();
            claimCase.setCreateTime(date);
            claimCase.setCreateBy(userid);
            claimCase.setUpdateTime(date);
            claimCase.setUpdateBy(userid);
            claimCase.setReportTime(convertStringToDate(temp.getReportTime()));
            claimCase.setCaseStatus(getCaseStatus(temp.getCaseStatus()));
            claimCase.setFirstStatus(getCaseStatus(temp.getCaseStatus()));
            save(claimCase);
            String caseId = claimCase.getId();
            // 4.保存案件理赔记录信息
            ClaimSettlementEntity claimSettlement = new ClaimSettlementEntity();
            claimSettlement.setCaseId(caseId);
            claimSettlement.setSettlementOrder(1);
            claimSettlement.setCaseStatus(getCaseStatus(temp.getCaseStatus()));
            claimSettlement.setAcceptorId(userid);
            claimSettlement.setAcceptorName(username);
            claimSettlement.setCreateBy(userid);
            claimSettlement.setCreateTime(date);
            claimSettlement.setUpdateTime(convertStringToDate(temp.getCloseTime()));
            claimSettlementService.save(claimSettlement);
            //保存诊疗信息t_treatment_info
            TreatmentInfoEntity treatmentInfoEntity = new TreatmentInfoEntity();
            treatmentInfoEntity.setCsId(claimSettlement.getId());
            if(StringUtils.isNotBlank(temp.getTreatAgainFlag())){
                if(temp.getTreatAgainFlag().equals("是")){
                    treatmentInfoEntity.setTreatAgainFlag(1);
                }else if(temp.getTreatAgainFlag().equals("否")){
                    treatmentInfoEntity.setTreatAgainFlag(0);
                }
            }
            treatmentInfoEntity.setFamilyWantAmount(AmountUtils.yuanToFenLong(temp.getFamilyWantAmount()));
            treatmentInfoEntity.setGetFileTime(convertStringToDate(temp.getGetFileTime()));
            treatmentInfoEntity.setSendCorpTime(convertStringToDate(temp.getSendCorpTime()));
            if(StringUtils.isNotBlank(temp.getTreatmentType())){
                if(temp.getTreatmentType().equals("门诊")){
                    treatmentInfoEntity.setTreatmentType(1);
                }else if(temp.getTreatmentType().equals("住院")){
                    treatmentInfoEntity.setTreatmentType(2);
                }
            }
            treatmentInfoEntity.setInvoiceAmount(AmountUtils.yuanToFenLong(temp.getInvoiceAmount()));
            treatmentInfoEntity.setCreateBy(userid);
            treatmentInfoEntity.setCreateTime(date);
            treatmentInfoService.save(treatmentInfoEntity);

            SettlementAmountEntity settlementAmountEntity = new SettlementAmountEntity();
            settlementAmountEntity.setTreatmentAmount(AmountUtils.yuanToFenLong(temp.getTreatmentAmount()));
            settlementAmountEntity.setDelayWorkAmount(AmountUtils.yuanToFenLong(temp.getDelayWorkAmount()));
            settlementAmountEntity.setDeathAmount(AmountUtils.yuanToFenLong(temp.getDeathAmount()));
            settlementAmountEntity.setDisabilityAmount(AmountUtils.yuanToFenLong(temp.getDisabilityAmount()));
            settlementAmountEntity.setDisabilityAppraisalAmount(AmountUtils.yuanToFenLong(temp.getDisabilityAppraisalAmount()));
            settlementAmountEntity.setPublicAmount(AmountUtils.yuanToFenLong(temp.getPublicAmount()));
            settlementAmountEntity.setEmployerAmount(AmountUtils.yuanToFenLong(temp.getEmployerAmount()));
            settlementAmountEntity.setTotalAmount(AmountUtils.yuanToFenLong(temp.getTotalAmount()));
            if(StringUtils.isNotBlank(temp.getDisabilityAppraisalLevel())){
                if(temp.getDisabilityAppraisalLevel().equals("无")){
                    settlementAmountEntity.setDisabilityAppraisalLevel(-1);
                }else
                if(temp.getDisabilityAppraisalLevel().equals("一级")){
                    settlementAmountEntity.setDisabilityAppraisalLevel(1);
                }else if(temp.getDisabilityAppraisalLevel().equals("二级")){
                    settlementAmountEntity.setDisabilityAppraisalLevel(2);
                }else if(temp.getDisabilityAppraisalLevel().equals("三级")){
                    settlementAmountEntity.setDisabilityAppraisalLevel(3);
                }else if(temp.getDisabilityAppraisalLevel().equals("四级")){
                    settlementAmountEntity.setDisabilityAppraisalLevel(4);
                }else if(temp.getDisabilityAppraisalLevel().equals("五级")){
                    settlementAmountEntity.setDisabilityAppraisalLevel(5);
                }else if(temp.getDisabilityAppraisalLevel().equals("六级")){
                    settlementAmountEntity.setDisabilityAppraisalLevel(6);
                }else if(temp.getDisabilityAppraisalLevel().equals("七级")){
                    settlementAmountEntity.setDisabilityAppraisalLevel(7);
                }else if(temp.getDisabilityAppraisalLevel().equals("八级")){
                    settlementAmountEntity.setDisabilityAppraisalLevel(8);
                }else if(temp.getDisabilityAppraisalLevel().equals("九级")){
                    settlementAmountEntity.setDisabilityAppraisalLevel(9);
                }else if(temp.getDisabilityAppraisalLevel().equals("十级")){
                    settlementAmountEntity.setDisabilityAppraisalLevel(10);
                }
            }
            settlementAmountEntity.setCsId(claimSettlement.getId());
            settlementAmountEntity.setCreateBy(userid);
            settlementAmountEntity.setCreateTime(date);
            settlementAmountService.save(settlementAmountEntity);
        }catch (Exception e){
            log.error("异常出发回滚了：" + temp.getNum() , e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ResponseData.error(temp.getNum());
        }
        return ResponseData.success(temp.getNum());
    }

    private Date convertStringToDate(String reportTime){
        if(StringUtils.isBlank(reportTime)){
            return null;
        }
        log.debug("reportTime:  "  + reportTime);
        return DateUtil.parseDate(reportTime);
    }

    /**
     * 导入总条数x条，成功y条，失败z条:序号（1,2,3）
     * */
    @Override
    public String getImportMsg() {
        if(error == 0){
            return String.format("成功%s条，失败0条。", success);
        }
        return String.format("成功%s条，失败%s条，失败数据序号：【%s】！", success, error, errorNums);
    }

    /**
     * 逻辑删除
     * @param id
     * @param userId
     * @return
     */
    @Override
    public boolean deleteById(String id, Long userId) {
        ClaimCaseEntity entity = new ClaimCaseEntity();
        entity.setId(id);
        entity.setEnableFlag(0);
        entity.setUpdateTime(new Date());
        entity.setUpdateBy(userId);
        return updateById(entity);
    }

    @Override
    public Page<PayOutRatioRsp> queryPayOutRatio(Page<PayOutRatioRsp> page, CasePayOutRatioReq req) {
        List<PayOutRatioRsp> list = getBaseMapper().queryPayOutRatio(page, req);
        return page.setRecords(list);
    }

    @Override
    public Page<CaseCloseRatioRsp> queryCaseCloseRatio(Page<CaseCloseRatioRsp> page, CaseCloseRatioReq req) {
        List<CaseCloseRatioRsp> list = getBaseMapper().queryCaseCloseRatio(page, req);
        page.setTotal(CollectionUtils.isNotEmpty(list) ? list.size() : 0);
        return page.setRecords(list);
    }

    @Override
    public Page<DisabilityLevelReportRsp> queryDisabilityLevelReport(Page<DisabilityLevelReportRsp> page, CaseCloseRatioReq req) {
        List<DisabilityLevelReportRsp> list = getBaseMapper().queryDisabilityLevelReport(page, req);
        if(CollectionUtils.isNotEmpty(list)){
            list = list.stream().peek(x-> x.setLevel(x.getLevelId()+"级")).collect(Collectors.toList());
        }
        return page.setRecords(list);
    }

    @Override
    public Page<DisabilityLevelReportRsp> querySelfPayAmountReport(Page<DisabilityLevelReportRsp> page, CaseCloseRatioReq req) {
        List<DisabilityLevelReportRsp> list = getBaseMapper().querySelfPayAmountReport(page, req);
        page.setTotal(CollectionUtils.isNotEmpty(list) ? list.size() : 0);
        return page.setRecords(list);
    }

    @Override
    public Page<PayOutRatioRsp> queryAccidentTypeRatio(Page<PayOutRatioRsp> page, CasePayOutRatioReq req) {
        List<PayOutRatioRsp> list = getBaseMapper().queryAccidentTypeRatio(page, req);
        if(CollectionUtils.isNotEmpty(list)){
            list = list.stream().peek(x->{
                if(x.getType() == 1){
                    x.setTypeName("医疗身故");
                }else if(x.getType() == 2){
                    x.setTypeName("伤残身故");
                }else if(x.getType() == 3){
                    x.setTypeName("交通身故");
                }else if(x.getType() == 4){
                    x.setTypeName("意外身故");
                }else if(x.getType() == 5){
                    x.setTypeName("疾病身故");
                }
            }).collect(Collectors.toList());
        }
        return page.setRecords(list);
    }

    /**
     * 案件状态: 1受理中 2 已提交保司 3 已结案 4 已撤销 5 诉讼中
     * @param caseStatus
     * @return
     */
    private Integer getCaseStatus(String caseStatus) {
        if(StringUtils.isBlank(caseStatus) || caseStatus.equals("受理中")){
            return 1;
        }else if(caseStatus.equals("已提交保司")){
            return 2;
        }else if(caseStatus.equals("已结案")){
            return 3;
        }else if(caseStatus.equals("已撤销")){
            return 4;
        }else if(caseStatus.equals("诉讼中")){
            return 5;
        }
        return 1;
    }

}
